import {
  ArgumentsHost,
  Catch,
  ExceptionFilter,
  HttpException,
  Logger,
  RpcExceptionFilter,
  WsExceptionFilter,
} from '@nestjs/common'
import { FastifyReply } from 'fastify'
import { Observable, of } from 'rxjs'
import { ResponseDtoFactory } from './response-dto-factory'

@Catch()
export class ResponseExceptionFilter implements ExceptionFilter, WsExceptionFilter, RpcExceptionFilter {
  private readonly logger = new Logger(ResponseExceptionFilter.name)
  private responseDtoFactory = new ResponseDtoFactory()

  catch(exception: any, host: ArgumentsHost): undefined // will be returned if host type is http or ws
  catch(exception: any, host: ArgumentsHost): Observable<any> // will be returned if host type is rpc
  catch(exception: any, host: ArgumentsHost): undefined | Observable<any> {
    const dto = this.responseDtoFactory.error(exception, this.logger)

    if (host.getType() === 'http') {
      const res = host.switchToHttp().getResponse<FastifyReply>()
      if (exception instanceof HttpException) {
        res.status(exception.getStatus?.() ?? 500)
      } else {
        res.status(500)
      }

      res.send(dto)
      return
    } else if (host.getType() === 'ws') {
      // websockets implemented in go.
    } else if (host.getType() === 'rpc') {
      return of([ dto ])
    }
  }
}
